Pressidian
花园入口
笔记
项目
关于
实验室
GitHub
花园入口
笔记
项目
关于
实验室
GitHub

KNOWLEDGE PATHS

笔记库
当前位置
笔记库/学习/408/数据结构

5.1 树

7 分钟阅读 · Note

目录树 578 篇

          • 3.1 栈
          • 4.1 串定义与基本操作
          • 5.1 树
          • 6.1 图的基本概念
          • 7.1 查找的基本概念
          • 8.1 排序基本概念
          • 第二章 线性表
          • 第一章 绪论
      • 论文
    • 笔记目录
    • CLAUDE.md
    • Vue 组件与 Render 函数

关联笔记 6

↗3.1 栈同一路径↗4.1 串定义与基本操作同一路径↗6.1 图的基本概念同一路径↗7.1 查找的基本概念同一路径↗8.1 排序基本概念同一路径↗第二章 线性表同一路径
  • 5.1 树

5.1 树

5.1.1 树的定义

![Pasted image 20251109182350](../../../_assets/0722359-Pasted image 20251109182350.png)

5.1.2 基本术语

路径是有向边 ![Pasted image 20251109182755](../../../_assets/321b7ae-Pasted image 20251109182755.png)

![Pasted image 20251109183049](../../../_assets/66a591d-Pasted image 20251109183049.png)

有序数与无序树

![Pasted image 20251109183153](../../../_assets/e731d3a-Pasted image 20251109183153.png)

森林

![Pasted image 20251109183250](../../../_assets/c6387db-Pasted image 20251109183250.png)

5.1.3 树的性质

除了根结点,每个结点都有一个入度 ![Pasted image 20251109183415](../../../_assets/51eeab4-Pasted image 20251109183415.png)

![Pasted image 20251109183625](../../../_assets/e3e5fe6-Pasted image 20251109183625.png)

![Pasted image 20251109183736](../../../_assets/de52b91-Pasted image 20251109183736.png) ![Pasted image 20251109183826](../../../_assets/f211063-Pasted image 20251109183826.png) ![Pasted image 20251109183906](../../../_assets/3071971-Pasted image 20251109183906.png)

![Pasted image 20251109184142](../../../_assets/3b0824c-Pasted image 20251109184142.png) ![Pasted image 20251109184206](../../../_assets/da2f7e9-Pasted image 20251109184206.png)

5.2 二叉树

5.2.1 基本概念

![Pasted image 20251109184434](../../../_assets/f4c88e7-Pasted image 20251109184434.png)

满二叉树与完全二叉树

![Pasted image 20251109184905](../../../_assets/44d3f66-Pasted image 20251109184905.png)

二叉排序树

![Pasted image 20251109185116](../../../_assets/78af3d1-Pasted image 20251109185116.png)

平衡二叉树

![Pasted image 20251109185231](../../../_assets/a202184-Pasted image 20251109185231.png)

5.2.2 二叉树的性质

![Pasted image 20251109185556](../../../_assets/a039c77-Pasted image 20251109185556.png)

![Pasted image 20251109185612](../../../_assets/a7c8041-Pasted image 20251109185612.png)

![Pasted image 20251109185701](../../../_assets/6b3ebfd-Pasted image 20251109185701.png)

![Pasted image 20251109185910](../../../_assets/2ce825f-Pasted image 20251109185910.png) ![Pasted image 20251109190029](../../../_assets/51bb02d-Pasted image 20251109190029.png)

![Pasted image 20251109190234](../../../_assets/7b482ec-Pasted image 20251109190234.png)

5.2.3 二叉树的存储结构

顺序存储

![Pasted image 20251109190604](../../../_assets/3611b4b-Pasted image 20251109190604.png)

![Pasted image 20251109190727](../../../_assets/03bc26b-Pasted image 20251109190727.png) 使用顺序存储二叉树来存储,只适合完全二叉树,会有大量空位: ![Pasted image 20251109191037](../../../_assets/8d4defd-Pasted image 20251109191037.png)

链式存储

n个结点,有n-1个指针指向结点(根结点没有),每个结点有两个指针域,共有2n个,剩余的n+1个指针域为null: ![Pasted image 20251109191235](../../../_assets/b3233f5-Pasted image 20251109191235.png)

代码实现: ![Pasted image 20251109191628](../../../_assets/df6f4ba-Pasted image 20251109191628.png)

5.3 二叉树的遍历

5.3.1 先中后序遍历(深度优先)

![Pasted image 20251109192415](../../../_assets/c0d6db4-Pasted image 20251109192415.png) ![Pasted image 20251109192650](../../../_assets/4df9e5c-Pasted image 20251109192650.png)

代码实现

调整visit()的位置就可以实现不同的算法: ![Pasted image 20251109192802](../../../_assets/528b86b-Pasted image 20251109192802.png)

先序是第一次访问的结点,中序是第二次访问的结点: ![Pasted image 20251109193230](../../../_assets/22da7e5-Pasted image 20251109193230.png)

求深度

![Pasted image 20251109193539](../../../_assets/d40a4aa-Pasted image 20251109193539.png)

5.3.2 层次遍历(广度优先)

![Pasted image 20251109193800](../../../_assets/390cf49-Pasted image 20251109193800.png)

代码实现

![Pasted image 20251109194027](../../../_assets/01d3fe3-Pasted image 20251109194027.png) 保存指针即可,可以减小空间消耗

5.3.3 遍历序列构造二叉树

只依靠一种遍历序列不可能构造出唯一的二叉树结构,至少两种且必须包括中序:

![Pasted image 20251109195252](../../../_assets/4e27541-Pasted image 20251109195252.png)

先序与中序

![Pasted image 20251109195701](../../../_assets/800e8b4-Pasted image 20251109195701.png) ![Pasted image 20251109195748](../../../_assets/52bff22-Pasted image 20251109195748.png) ![Pasted image 20251109195811](../../../_assets/bf9bbcc-Pasted image 20251109195811.png)

后序与中序

原理与先序一样

层次与中序

![Pasted image 20251109200220](../../../_assets/fe2edfd-Pasted image 20251109200220.png)

5.3.4 线索二叉树

在普通的二叉树中去通过一个非根结点去遍历或寻找它的前驱与后继是很困难的

中序线索二叉树

![Pasted image 20251109201735](../../../_assets/1e74012-Pasted image 20251109201735.png) 寻找中序后继next: ![Pasted image 20251111165126](../../../_assets/24bf413-Pasted image 20251111165126.png)

寻找中序前驱pre: ![Pasted image 20251111165412](../../../_assets/d417e44-Pasted image 20251111165412.png)

先序线索二叉树

寻找先序后继next: ![Pasted image 20251111170026](../../../_assets/632331d-Pasted image 20251111170026.png)

寻找先序前驱pre: ![Pasted image 20251111170343](../../../_assets/564333b-Pasted image 20251111170343.png)

  • 如果使用三叉链表(有指向父节点的指针) ![Pasted image 20251111170656](../../../_assets/0cafd94-Pasted image 20251111170656.png)

后序线索二叉树

后序前驱: ![Pasted image 20251111171315](../../../_assets/800e6c2-Pasted image 20251111171315.png) 后序后继: ![Pasted image 20251111171712](../../../_assets/b07a9f4-Pasted image 20251111171712.png) ![Pasted image 20251111171615](../../../_assets/3640df4-Pasted image 20251111171615.png) 总结上述三种: ![Pasted image 20251111171805](../../../_assets/83ff425-Pasted image 20251111171805.png)

存储结构

![Pasted image 20251109202007](../../../_assets/d9891f4-Pasted image 20251109202007.png)

![Pasted image 20251109202033](../../../_assets/7f3a581-Pasted image 20251109202033.png)

代码实现

中序线索化: ![Pasted image 20251109203009](../../../_assets/d0f554b-Pasted image 20251109203009.png)

另一种实现方式: ![Pasted image 20251109204300](../../../_assets/cb2ec72-Pasted image 20251109204300.png) 前序和后序调整visit()的代码顺序即可,但是注意在先序线索化的时候要判断某个结点的左孩子是否为线索化的前驱,这样会有循环问题,后序没有这个问题。 ![Pasted image 20251109203809](../../../_assets/b6d5ab1-Pasted image 20251109203809.png) 无论哪种线索化,都要注意最后一个结点的右孩子和rtag的处理

5.4 树的结构

5.4.1 树的存储结构

双亲表示法(顺序存储)

树中每个非跟结点都有一个根结点。找父节点方便,但是找孩子结点困难,需要遍历数组。同时这种方式可以表示森林 ![Pasted image 20251111172554](../../../_assets/9d75f1f-Pasted image 20251111172554.png)

孩子表示法(顺序+链式存储)

便于找孩子,找父节点困难。可以表示森林,但要记录多个跟结点。 ![Pasted image 20251111173043](../../../_assets/851f64d-Pasted image 20251111173043.png)

孩子兄弟表示法(链式存储)

也可以表示森林,森林中每棵树视为兄弟关系 ![Pasted image 20251111174130](../../../_assets/5c4e121-Pasted image 20251111174130.png)

5.4.2 树、森林二叉树之间的转换

树、森林转化为二叉树

使用孩子兄弟表示法 ![Pasted image 20251111174900](../../../_assets/b9bdf14-Pasted image 20251111174900.png)

![Pasted image 20251111175013](../../../_assets/1177b2e-Pasted image 20251111175013.png)

二叉树转化为树、森林

树: ![Pasted image 20251111175533](../../../_assets/475374f-Pasted image 20251111175533.png)

森林: ![Pasted image 20251111175655](../../../_assets/d81178c-Pasted image 20251111175655.png)

5.4.3 树与森林的遍历

树的遍历

先根(深度): ![Pasted image 20251111181605](../../../_assets/bef94fe-Pasted image 20251111181605.png)

后根(深度): ![Pasted image 20251111181749](../../../_assets/2f6ba46-Pasted image 20251111181749.png)

层次(深度): ![Pasted image 20251111182000](../../../_assets/361b53d-Pasted image 20251111182000.png)

森林的遍历

先序:等同于对每棵子树做先根遍历,也等同于对森林转化的二叉树的先序遍历 ![Pasted image 20251111182240](../../../_assets/30e4395-Pasted image 20251111182240.png)

中序:等同于对每棵子树做后根遍历,也等同于对森林转化的二叉树的中序遍历 ![Pasted image 20251111182615](../../../_assets/d11ff8b-Pasted image 20251111182615.png)

5.5 树的应用

5.5.1 哈夫曼树

带权路径长度(WPL)最小的二叉树,可能不唯一 ![Pasted image 20251111182949](../../../_assets/59c18a0-Pasted image 20251111182949.png)

![Pasted image 20251111183102](../../../_assets/e3957e1-Pasted image 20251111183102.png) ![Pasted image 20251111183030](../../../_assets/be8e810-Pasted image 20251111183030.png)

构造哈夫曼树

![Pasted image 20251111183310](../../../_assets/241d21e-Pasted image 20251111183310.png) ![Pasted image 20251111183351](../../../_assets/0a8baa5-Pasted image 20251111183351.png)

哈夫曼编码(可变长编码)

对于使用固定长度编码的树,所传递的信息的效率较低,也就是WPL较大,可以使用哈夫曼树来优化(编码结果可能不唯一),并且解码不会有歧义(前缀编码): ![Pasted image 20251111184403](../../../_assets/2a6eaca-Pasted image 20251111184403.png)

5.2.1 并查集

在集合这种逻辑结构中,两个元素之间的关系是从属于同一集合或从属于不同集合。使用树来表示一个集合,双亲表示法(顺序存储)更适合实现并查集 ![Pasted image 20251111190344](../../../_assets/bee2dec-Pasted image 20251111190344.png)

代码实现

![Pasted image 20251111190638](../../../_assets/ab66639-Pasted image 20251111190638.png)

性能分析

时间复杂度:Find:O(n) ,Union:O(1) 对于合并集合(树)的过程,要尽可能的树“矮胖”(小树合并到大树中),以在Find的过程过程中尽可能减少访问结点的次数: ![Pasted image 20251111191242](../../../_assets/acb44bd-Pasted image 20251111191242.png)

算法优化

优化Union: ![Pasted image 20251111192819](../../../_assets/f099b6d-Pasted image 20251111192819.png)

优化Find: ![Pasted image 20251111193557](../../../_assets/7e9e09e-Pasted image 20251111193557.png)